package com.wooming.myserver.service.impl;

import com.wooming.myserver.dto.HeadshotDTO;
import com.wooming.myserver.dto.JwtDTO;
import com.wooming.myserver.entity.User;
import com.wooming.myserver.mapper.UserMapper;
import com.wooming.myserver.security.JWT;
import com.wooming.myserver.service.inter.HeadshotService;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.io.*;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardCopyOption;
import java.util.Objects;

/**
 * 头像服务实现类
 *
 * @author Wooming 2025/05/22
 */
@Service
public class HeadshotServiceImpl implements HeadshotService {
    // 头像存储根路径
    private final Path root = Path.of("headshots");
    // 依赖项
    private final UserMapper userMapper;

    @Autowired
    public HeadshotServiceImpl(UserMapper userMapper) {
        this.userMapper = userMapper;
    }

    @Override
    public User verify(String jwt) throws Exception {
        JwtDTO jwtDTO = JWT.decode(jwt);
        if (jwtDTO == null) {
            return null;
        }
        return userMapper.findById(jwtDTO.getSub());
    }

    @Override
    public boolean upload(User user, HeadshotDTO headshotDTO) throws Exception {
        // 构建上传路径并检查安全
        MultipartFile file = headshotDTO.getFile();
        Path filePath = root.resolve(Objects.requireNonNull(file.getOriginalFilename()))
                .normalize().toAbsolutePath();
        if (!filePath.getParent().equals(root.toAbsolutePath())) {
            throw new Exception("非法路径");
        }

        //  清理原文件
        Path oldFilePath = root.resolve(user.getHeadshotPath()).normalize().toAbsolutePath();
        if (Files.exists(oldFilePath) && !user.getHeadshotPath().endsWith("default.png")) {
            Files.delete(oldFilePath);
        }

        // 检查是否有重名文件
        if (Files.exists(filePath)) {
            // 更改文件名:  文件名_时间戳.后缀
            String newFileName = filePath.getFileName().toString().split("\\.")[0] + "_" + System.currentTimeMillis() + "." + filePath.getFileName().toString().split("\\.")[1];
            filePath = root.resolve(newFileName).normalize().toAbsolutePath();
        }

        // 替换文件路径并更新数据库
        user.setHeadshotPath(filePath.toString());
        userMapper.update(user);

        // 保存文件
        Files.copy(file.getInputStream(), filePath, StandardCopyOption.REPLACE_EXISTING);
        return true;
    }

    @Override
    public boolean sendHeadshot(HttpServletResponse response, User user) throws Exception {
        // 构建文件路径
        Path filePath = Paths.get(user.getHeadshotPath());

        // 判断文件是否存在
        if (!Files.exists(filePath) || !Files.isReadable(filePath)) {
            filePath = Paths.get("headshots/default.png");
        }

        // 获取文件
        File file = new File(filePath.toUri());

        // 设置响应头
        String contentType;
        if (filePath.toString().endsWith(".png")) {
            contentType = "image/png";
        } else if (filePath.toString().endsWith(".jpg") || filePath.toString().endsWith(".jpeg")) {
            contentType = "image/jpeg";
        } else {
            contentType = "application/octet-stream";
        }
        response.setContentType(contentType);
        response.setHeader("Cache-Control", "no-cache, no-store, must-revalidate"); // 禁止缓存,每次请求都重新加载图片

        // 写入输出流
        try (
                OutputStream out = response.getOutputStream();
                FileInputStream in = new FileInputStream(file)
        ) {
            // 写入输出流
            byte[] buffer = new byte[1024];
            int bytesRead;
            while ((bytesRead = in.read(buffer)) != -1) {
                out.write(buffer, 0, bytesRead);
            }

            // 关闭流
            out.close();
        } catch (Exception e) {
            throw new Exception("文件传输错误");
        }
        return true;
    }
}
